home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 February: Tool Chest / Dev.CD Feb 95 / Dev.CD Feb 95.toast / New System Software Extensions / ASLM SDK v1.1.2 / ASLM Examples / Inspector / Sources / Application.cp next >
Encoding:
Text File  |  1994-11-21  |  13.5 KB  |  551 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Application.cp
  3.  
  4.     Contains:    TApplication implementation.
  5.  
  6.     Copyright:    © 1991-1993 by Apple Computer, Inc., all rights reserved.
  7.  
  8. */
  9.  
  10. #ifndef __TYPES__
  11. #include <Types.h>
  12. #endif
  13.  
  14. #if MAC68K
  15. #ifndef __QUICKDRAW__
  16. #include <QuickDraw.h>
  17. #endif
  18. #endif
  19.  
  20. #ifndef __FONTS__
  21. #include <Fonts.h>
  22. #endif
  23. #ifndef __EVENTS__
  24. #include <Events.h>
  25. #endif
  26. #ifndef __WINDOWS__
  27. #include <Windows.h>
  28. #endif
  29. #ifndef __MENUS__
  30. #include <Menus.h>
  31. #endif
  32. #ifndef __DIALOGS__
  33. #include <Dialogs.h>
  34. #endif
  35. #ifndef __TOOLUTILS__
  36. #include <ToolUtils.h>
  37. #endif
  38. #ifndef __MEMORY__
  39. #include <Memory.h>
  40. #endif
  41. #ifndef __SEGLOAD__
  42. #include <SegLoad.h>
  43. #endif
  44. #ifndef __OSUTILS__
  45. #include <OSUtils.h>
  46. #endif
  47. #ifndef __TRAPS__
  48. #include <Traps.h>
  49. #endif
  50.  
  51. #ifndef __APPLICATION__
  52. #include <Application.h>
  53. #endif
  54. #ifndef __SIMPLECOMMON__
  55. #include "SimpleCommon.h"
  56. #endif
  57. #ifndef __APPLICATIONCOMMON__
  58. #include "ApplicationCommon.h"
  59. #endif
  60. #ifndef __DOCUMENT__
  61. #include <Document.h>
  62. #endif
  63.  
  64. #include "TrapAvailable.cp"
  65.  
  66. // OSEvent is the event number of the suspend/resume and mouse-moved events sent
  67. // by MultiFinder. Once we determine that an event is an osEvent, we look at the
  68. // high byte of the message sent to determine which kind it is. To differentiate
  69. // suspend and resume events we check the resumeMask bit.
  70. const short kOsEvent = app4Evt;                // event used by MultiFinder
  71. const short kSuspendResumeMessage = 0x01;    // high byte of suspend/resume event message
  72. const short kClipConvertMask = 0x02;        // bit of message field clip conversion
  73. const short kResumeMask = 0x01;                // bit of message field for resume vs. suspend
  74. const short kMouseMovedMessage = 0xFA;        // high byte of mouse-moved event message
  75.  
  76. /*******************************************************************************
  77. ** PUBLIC Constructor/Destructor
  78. ********************************************************************************/
  79.  
  80. TApplication::TApplication()
  81. {
  82.     fCurDoc = NULL;
  83.     fDone = NULL;
  84.     fInBackground = false;
  85.     fMouseRgn = NULL;
  86.     fWhichWindow = NULL;
  87.     fqd = NULL;
  88. }
  89.  
  90. TApplication::TApplication(Ptr qdPtr, Boolean initToolbox)
  91. {
  92.     InitApplication(qdPtr, initToolbox);
  93. }
  94.  
  95. TApplication::~TApplication(void)
  96. {
  97.     //Trace("Disposing TApplication\n");
  98.     delete fDocList;
  99. }
  100.  
  101. /*******************************************************************************
  102. ** PRIVATE InitApplication
  103. ********************************************************************************/
  104.  
  105. void TApplication::InitApplication(Ptr qdPtr, Boolean initToolbox)
  106. {
  107.     SysEnvRec envRec;
  108.     long stkNeeded, heapSize;
  109.     fqd = (qdRec*)qdPtr;
  110.  
  111.     // initialize Mac Toolbox components
  112.     if (initToolbox) {
  113.         InitGraf(&fqd->thePort);
  114.         InitFonts();
  115.         InitWindows();
  116.         InitMenus();
  117.         TEInit();
  118.         InitDialogs(NULL);
  119.         InitCursor();
  120.     }
  121.  
  122.     // ignore the error returned from SysEnvirons; even if an error occurred,
  123.     // the SysEnvirons glue will fill in the SysEnvRec
  124.     (void) SysEnvirons(curSysEnvVers, &envRec);
  125.  
  126.     // Are we running on a 128K ROM machine or better???
  127.     if (envRec.machineType < 0) {
  128.         TApplication::BigBadError(kApplicationErrStrings,eWrongMachine); // if not, alert & quit
  129.     }
  130.  
  131.     // if we need more stack space, get it now
  132.     stkNeeded = StackNeeded();
  133.     if (stkNeeded > StackSpace())
  134.       {
  135.         // new address is heap size + current stack - needed stack
  136.         SetApplLimit((Ptr) ((long) GetApplLimit() - stkNeeded + StackSpace()));
  137.       }
  138.  
  139.     // Check for minimum heap size
  140.     heapSize = (long) GetApplLimit() - (long) ApplicZone();
  141.     if (heapSize < HeapNeeded()) {
  142.         TApplication::BigBadError(kApplicationErrStrings,eSmallSize);
  143.     }
  144.  
  145.     // expand the heap so new code segments load at the top
  146.     MaxApplZone();
  147.  
  148.     // allocate an empty document list
  149.     fDocList = new TDocumentList;
  150.  
  151.     // check to see if WaitNextEvent is implemented
  152.     fHaveWaitNextEvent = TrapAvailable(_WaitNextEvent);
  153.  
  154.     // initialize our class variables
  155.     fCurDoc = NULL;
  156.     fDone = false;
  157.     fInBackground = false;
  158.     fMouseRgn = NULL;
  159.     fWhichWindow = NULL;
  160. }
  161.  
  162. /**********************************************************************
  163. ** PUBLIC EventLoop
  164. ***********************************************************************/
  165.  
  166. void TApplication::EventLoop(void)
  167. {
  168.     int gotEvent;
  169.     EventRecord tEvt;
  170.  
  171.     SetUp();                    // call setup routine
  172.     DoIdle();                    // do idle once
  173.  
  174.     while (fDone == false)
  175.       {
  176.         // always set up fWhichWindow before doing anything
  177.         fWhichWindow = FrontWindow();
  178.         // see if window belongs to a document
  179.         fCurDoc = fDocList->FindDoc(fWhichWindow);
  180.         // make sure we always draw into correct window
  181.         SetPort(fWhichWindow);
  182.  
  183.         DoIdle();            // call idle time handler
  184.         
  185.         if (fHaveWaitNextEvent)
  186.           {
  187.             gotEvent = WaitNextEvent(everyEvent, &tEvt, SleepVal(), fMouseRgn);
  188.           }
  189.         else
  190.           {
  191.             SystemTask();
  192.             gotEvent = GetNextEvent(everyEvent, &tEvt);
  193.           }
  194.         fTheEvent = tEvt;
  195.  
  196.         // make sure we got a real event
  197.         if ( gotEvent )
  198.           {
  199.             AdjustCursor();
  200.             switch (fTheEvent.what)
  201.               {
  202.                 case mouseDown :
  203.                     DoMouseDown();
  204.                     break;
  205.                 case mouseUp :
  206.                     DoMouseUp();
  207.                     break;
  208.                 case keyDown :
  209.                 case autoKey :
  210.                     DoKeyDown();
  211.                     break;
  212.                 case updateEvt :
  213.                     DoUpdateEvt();                
  214.                     break;
  215.                 case diskEvt :
  216.                     DoDiskEvt();
  217.                     break;
  218.                 case activateEvt :
  219.                     DoActivateEvt();
  220.                     break;
  221.                 case kOsEvent :
  222.                     DoOSEvent();
  223.                     break;
  224.                 default :
  225.                     break;
  226.               } // end switch (fTheEvent.what)
  227.           }
  228.         AdjustCursor();
  229.       }
  230.     // call cleanup handler
  231.     CleanUp();
  232. }
  233.  
  234. /**********************************************************************
  235. ** PUBLIC StackNeeded/HeapNeeded
  236. ***********************************************************************/
  237.  
  238. long TApplication::StackNeeded()
  239. {
  240.     return 0;
  241. }
  242.  
  243. long TApplication::HeapNeeded()
  244. {
  245.     return 0;
  246. }
  247.  
  248. /**********************************************************************
  249. ** PUBLIC SetUp/Cleanup
  250. ***********************************************************************/
  251.  
  252. void TApplication::SetUp()
  253. {
  254.     // Run before event loop starts
  255. }
  256.  
  257. void TApplication::CleanUp()
  258. {
  259.     // run at end of loop
  260. }
  261.  
  262. /**********************************************************************
  263. ** PUBLIC ExitLoop
  264. ***********************************************************************/
  265.  
  266. void TApplication::ExitLoop(void)
  267. {
  268.     fDone = true;
  269. }
  270.  
  271. /**********************************************************************
  272. ** PUBLIC DoIdle
  273. ***********************************************************************/
  274.  
  275. void TApplication::DoIdle()
  276. {
  277.     // idle time handler (blink caret, background tasks)
  278. }
  279.  
  280. /**********************************************************************
  281. ** PUBLIC AdjustMenus
  282. ***********************************************************************/
  283.  
  284. void TApplication::AdjustMenus()
  285. {
  286.     // menu updater routine
  287. }
  288.  
  289. /**********************************************************************
  290. ** PUBLIC DoKeyDown
  291. ***********************************************************************/
  292.  
  293. void TApplication::DoKeyDown(void)
  294. {
  295.     char key;
  296.     long mResult;
  297.  
  298.     key = (char) (fTheEvent.message & charCodeMask);
  299.     if ((fTheEvent.modifiers & cmdKey) && (fTheEvent.what == keyDown))
  300.       {
  301.         // only do command keys if we are not autokeying
  302.         AdjustMenus();                    // make sure menus are up to date
  303.         mResult = MenuKey(key);
  304.         if (mResult != 0)                // if it wasn't a menu key, pass it through
  305.           {
  306.             DoMenuCommand(HiWrd(mResult), LoWrd(mResult));
  307.             return;
  308.           }
  309.       }
  310.     if (fCurDoc != NULL)
  311.       {
  312.         EventRecord tEvt;
  313.  
  314.         // we copy event record so that we don't pass reference to object field 
  315.         tEvt = fTheEvent;
  316.         fCurDoc->DoKeyDown(&tEvt);
  317.       }
  318. }
  319.  
  320. /**********************************************************************
  321. ** PUBLIC DoActivateEvt/DoUpdateEvt
  322. ***********************************************************************/
  323.  
  324. void TApplication::DoActivateEvt(void)
  325. {
  326.     // event record contains window ptr
  327.     fWhichWindow = (WindowPtr) fTheEvent.message;
  328.     // see if window belongs to a document
  329.     fCurDoc = fDocList->FindDoc(fWhichWindow);
  330.     SetPort(fWhichWindow);
  331.  
  332.     if (fCurDoc != NULL)
  333.       fCurDoc->DoActivate((fTheEvent.modifiers & activeFlag) != 0);
  334. }
  335.  
  336. void TApplication::DoUpdateEvt(void)
  337. {
  338.     // event record contains window ptr
  339.     fWhichWindow = (WindowPtr) fTheEvent.message;
  340.     // see if window belongs to a document
  341.     fCurDoc = fDocList->FindDoc(fWhichWindow);
  342.     SetPort(fWhichWindow);
  343.  
  344.     if (fCurDoc != NULL)
  345.       fCurDoc->DoUpdate();
  346. }
  347.  
  348. /**********************************************************************
  349. ** PUBLIC DoOSEvent
  350. ***********************************************************************/
  351.  
  352. void TApplication::DoOSEvent(void)
  353. {
  354.     Boolean doConvert;
  355.     unsigned char evType;
  356.  
  357.     // is it a multifinder event?
  358.     evType = (unsigned char) (fTheEvent.message >> 24) & 0x00ff;
  359.     switch (evType) {     // high byte of message is type of event
  360.         case kMouseMovedMessage :
  361.             DoIdle();                    // mouse-moved is also an idle event
  362.             break;
  363.         case kSuspendResumeMessage :
  364.             doConvert = (fTheEvent.message & kClipConvertMask) != 0;
  365.             fInBackground = (fTheEvent.message & kResumeMask) == 0;
  366.             if (fInBackground)
  367.               DoSuspend(doConvert);
  368.             else DoResume(doConvert);
  369.             break;
  370.     }
  371. }
  372.  
  373. /**********************************************************************
  374. ** PUBLIC DoMouseDown
  375. ***********************************************************************/
  376.  
  377. void TApplication::DoMouseDown(void)
  378. {
  379.     long mResult;
  380.     short partCode;
  381.     WindowPtr tWind;
  382.     EventRecord tEvt;
  383.  
  384.     // gotta watch those object field dereferences
  385.     partCode = FindWindow(fTheEvent.where, &tWind);
  386.     fWhichWindow = tWind;
  387.     tEvt = fTheEvent;
  388.     switch (partCode)
  389.       {
  390.         case inSysWindow :
  391.             DoMouseInSysWindow();
  392.             break;
  393.         case inMenuBar :
  394.             AdjustMenus();
  395.             mResult = MenuSelect(tEvt.where);
  396.             if (mResult != 0)
  397.               DoMenuCommand(HiWrd(mResult),LoWrd(mResult));
  398.             break;
  399.         case inGoAway :
  400.             DoGoAway();                    
  401.             break;
  402.         case inDrag :
  403.             DoDrag();
  404.             break;
  405.         case inGrow :
  406.             if (fCurDoc != NULL)
  407.               fCurDoc->DoGrow(&tEvt);                    
  408.             break;
  409.         case inZoomIn :
  410.         case inZoomOut :
  411.             if ((TrackBox(fWhichWindow, tEvt.where, partCode)) &&
  412.                 (fCurDoc != NULL))
  413.               fCurDoc->DoZoom(partCode);
  414.             break;
  415.         case inContent :
  416.             // If window is not in front, make it so
  417.             if ( fWhichWindow != FrontWindow() )
  418.               SelectWindow(fWhichWindow);
  419.             else if (fCurDoc != NULL)
  420.               fCurDoc->DoContent(&tEvt);                    
  421.             break;
  422.       }
  423. }
  424.  
  425. /**********************************************************************
  426. ** PUBLIC DoMouseInSysWindow
  427. ***********************************************************************/
  428.  
  429. void TApplication::DoMouseInSysWindow()
  430. {
  431.     SystemClick(&fTheEvent, fWhichWindow);
  432. }
  433.  
  434. /**********************************************************************
  435. ** PUBLIC DoDrag
  436. ***********************************************************************/
  437.  
  438. void TApplication::DoDrag(void)
  439. {
  440.     DragWindow(fWhichWindow, fTheEvent.where, &fqd->screenBits.bounds);
  441. }
  442.  
  443. /**********************************************************************
  444. ** PUBLIC DoGoAway
  445. ***********************************************************************/
  446.  
  447. void TApplication::DoGoAway(void)
  448. {
  449.     if (TrackGoAway(fWhichWindow, fTheEvent.where)) {
  450.         if (fCurDoc != NULL)
  451.             HideWindow(fCurDoc->GetDocWindow());
  452.         else
  453.             CloseDeskAcc(((WindowPeek) fWhichWindow)->windowKind);
  454.  
  455.         // make sure our current document/window references are valid
  456.         fWhichWindow = FrontWindow();
  457.         if (fWhichWindow != NULL) {
  458.             fCurDoc = fDocList->FindDoc(fWhichWindow);
  459.             SetPort(fWhichWindow);
  460.         }
  461.         else fCurDoc = NULL;
  462.     }
  463. }
  464.  
  465. /**********************************************************************
  466. ** PUBLIC AdjustCursor
  467. ***********************************************************************/
  468.  
  469. void TApplication::AdjustCursor()
  470. {
  471.     // cursor adjust routine, should setup mouseRgn
  472. }
  473.  
  474. /**********************************************************************
  475. ** PUBLIC DoMenuCommand
  476. ***********************************************************************/
  477.  
  478. void TApplication::DoMenuCommand(short, short)
  479. {
  480. }
  481.  
  482. /**********************************************************************
  483. ** PUBLIC DoSuspend/DoResume
  484. ***********************************************************************/
  485.  
  486. void TApplication::DoSuspend(Boolean doClipConvert)
  487. {
  488.     doClipConvert = false;        // this is here because I HATE compiler warnings!!
  489.     if (fCurDoc != NULL)
  490.       fCurDoc->DoActivate(!fInBackground);
  491. }
  492.  
  493. void TApplication::DoResume(Boolean doClipConvert)
  494. {
  495.     doClipConvert = false;        // this is here because I HATE compiler warnings!!
  496.     if (fCurDoc != NULL)
  497.       fCurDoc->DoActivate(!fInBackground);
  498. }
  499.  
  500. /**********************************************************************
  501. ** PUBLIC DoMenuCommand
  502. ***********************************************************************/
  503.  
  504. void TApplication::DoMouseUp()
  505. {
  506. }
  507.  
  508. /**********************************************************************
  509. ** PUBLIC DoDiskEvt
  510. ***********************************************************************/
  511.  
  512. void TApplication::DoDiskEvt()
  513. {
  514. }
  515.  
  516. /**********************************************************************
  517. ** PUBLIC SleepVal
  518. ***********************************************************************/
  519.  
  520. unsigned long TApplication::SleepVal()
  521. {
  522.     return 20;        // how long to sleep in WaitNextEvent
  523. }
  524.  
  525. /**********************************************************************
  526. **  TApplication static methods
  527. ***********************************************************************/
  528.  
  529. void TApplication::AlertUser(short errResID, short errCode)
  530. {
  531.     Str255 message;
  532.     long savedRefNum;
  533.     GetLocalLibraryFile()->Preflight(savedRefNum);
  534.  
  535.     GetIndString(message, errResID, errCode);
  536.     #if qDebug
  537.     if (message[0] == 0)
  538.         DebugStr((ConstStr255Param)"\pTApplication::AlertUser could not get error string.");
  539.     #endif
  540.     ParamText(message, (ConstStr255Param)"\p", (ConstStr255Param)"\p", (ConstStr255Param)"\p");
  541.     (void) Alert(rUserAlert, NULL);
  542.  
  543.     GetLocalLibraryFile()->Postflight(savedRefNum);
  544. }
  545.  
  546. void TApplication::BigBadError(short errResID, short errCode)
  547. {
  548.     TApplication::AlertUser(errResID,errCode);
  549.     ExitToShell();
  550. }
  551.